-
Notifications
You must be signed in to change notification settings - Fork 1.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for frozen objects #6590
Conversation
# Conflicts: # realm/realm-library/src/main/cpp/io_realm_internal_OsObject.cpp # realm/realm-library/src/main/cpp/io_realm_internal_OsResults.cpp # realm/realm-library/src/main/cpp/io_realm_internal_core_IncludeDescriptor.cpp # realm/realm-library/src/main/cpp/object-store # realm/realm-library/src/main/java/io/realm/RealmCache.java
# Conflicts: # realm/realm-library/src/main/cpp/object-store
# Conflicts: # CHANGELOG.md # dependencies.list # realm/realm-library/src/androidTest/java/io/realm/RealmTests.java # realm/realm-library/src/androidTest/java/io/realm/internal/JNIQueryTest.java # realm/realm-library/src/main/cpp/object-store # version.txt
Table table = realm.getTable(PrimaryKeyAsString.class); | ||
assertNotNull(OsObjectStore.getPrimaryKeyForObject(realm.getSharedRealm(), PrimaryKeyAsString.CLASS_NAME)); | ||
assertTrue(table.hasSearchIndex(table.getColumnKey("name"))); | ||
assertFalse(table.hasSearchIndex(table.getColumnKey("name"))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Primary keys are not indexed by default anymore? 🤔 Or only on String primary keys?
Will people need to write a migration to handle this change? IIRC index changes are destructive, too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With Core 6 we are mapping user defined String primary keys to our internal ObjectId which is faster so the index isn't strictly needed for looking up single objects.
That said, it is possible that we are forgetting about some use cases or that we are missing some upgrade tests. Thanks for pointing it out 👏
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is no migration needed, there's a test covering this use case in d113014#diff-fe5ca9f6e0254b639a10bcc000406fdbR1439
The branch should now be up to date with the Core-6 branch and all test parses. @nhachicha |
realm/realm-library/src/androidTest/java/io/realm/RxJavaTests.java
Outdated
Show resolved
Hide resolved
realm/realm-library/src/androidTest/java/io/realm/RxJavaTests.java
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's time to ship this to Core6 branch, nice job 👏
* WIP Core6 integration * Update tests & OS * Disable file download if custom core path is set * Latest Core 12fd1cdd44eacf7cda7c9d5e8a5618f0704ba657 fixes some Sort disabled tests * Updated disabled tests, with reference to their issue. * Update reference to disabled test * - Removed a test non relevant in Core6 - Update disabled test with reference to issue * Update disabled test with reference to the issue * Enabling a test (passing with new Core/OS 🎉) * - Behaviour of stopWaitForChange changed in Core6 causing all waiting threads to be released, adapting tests accordingly & deprecated the usage of `stopWaitForChange` & `waitForChange` * Disabled tests concerning nullability (issue with test logic and Core crash) * Better kotlin tests * Add WIP support for TableRef instead of Table * Use TableRef instead of Table * Remove TBL macro * Reference open Java issue with regard to changes to fileformat upgrades. * Use Cores set_nullability * Updated core bug references * Fixing library benchmark * Enable tests after fixes in Core * Re-enable test * Re-enable more tests * Fix library benchmark project so it can load in Android Studio * Update test file and re-enable tests * Update various tests & using latest Core-6 branch from OS * - Removed usage of indices via colkey2spec_ndx - Renamed indices based method to column key - Updated OS commit to fix https://github.com/realm/realm-object-store/issues/678 * Fixes to upgrade to origin/master * Parse gradle root level properties to sub projects * - Enabling more tests, now all tests passes, sync integration tests are still failing because of https://github.com/realm/realm-object-store/issues/848 * update OS commit * Adapt to OS being behind master * - Applying disabled C++ compile flag - Cleanup * Test are passing * - Update dependencies - Rename ROW to OBJ * Update OS commit * fixed PMD rule * reverting check on valid ColKey since `bool(ColKey(-1))` returns true instead of false * - Disabling Sync iNtegration Flaky Tests * Making sure TableRef is used instead of Table* * More usage of TableRef vs Table* * remove OsObjectBuilder#maxColumnIndex() & ObjectSchemaInfo#getMaxColumnIndex() * Updated the annotation processor naming to use ColKey instead of index * Enabling/rewrote indicies based tests again * Remove usage of TR_ENTER_PTR * - Renaming Table#isAttached to Table#isValid - Clearing TODO/FIXME * Re-add missing benchmark files * Newlines * Cleanup & update OS Core6 branch * Update OS * Update to latest OS/Core * Disabling failing test on CI * Update to origin/master & uses a temporary OS branch with manual sync session creation commit cherry-picked * Update to latest OS/Core * Adding missing file * Fix flaky test * Added a test to check the Core6 no automatic index addition on String PK on an existing Core5 file * adding missing file * Add support for frozen objects (#6590) * PR feedback Cleanup & update to latest Core/OS versions * Annotation processor: using ColKey instead of index * PR feedback * Bumped minSDK * Update AP test * Fix transform crashing when you delete transformed objects (#6680) * Add multi-threaded stress test (#6677) * Add multi-threaded stress set * PR feedback. Use thread pool with variable amount of threads for reuse. * Better support for Gradle offline mode (#6692) * Update ReLinker (#6710) * Upgrade to latest version of Sync and Core (#6723) * Release v6.1.0 * Prepare next release v6.1.1-SNAPSHOT * Prepare for next dev iteration * cleanup * update deps * Updating tests * Update OS commit * Removed unused import * Update CHANGELOG.md Co-Authored-By: Christian Melchior <christian@ilios.dk> * Update CHANGELOG.md Co-authored-by: Christian Melchior <christian@ilios.dk>
Closes #4291
Closes #1208 ( most of it. There is still an open question about schedulers)
Blocked by:
This PR adds support for frozen Realm objects. The major benefit of frozen objects is that they are not thread confined and can thus be accessed on any thread. This is especially important for most kinds of stream-based architectures (which is most of them at this point).
The trade-off is that the objects are then immutable (which is actually considered a positive for most reactive architectures on Android)
High level API
Semantics
Freezing an object will freeze the entire object graph at that version, effectively turning it read-only. Doing this will also lift the thread-confined restriction on it.
These are still to be decided, but so far I'm envisioning the following
liveRealm.copyToRealmOrUpdate(frozenObject)
should work the same way as using unmanaged objects.Open design questions
Realm.getLocalInstanceCount(config)
:What are the semantics of
Realm.getLocalInstanceCount(config)
for frozen Realms?For now, globalCount == LocalThreadCount for frozen Realms, since these Realms are not thread constrained.
What are the semantics if the live Realm spawning frozen Realms is closed?
There are conflicting interests in terms of making it easy to reason about a Realm files life cycle vs. the Java objects. I.e. it becomes difficult to close a Realm file if frozen objects cannot easily close their Realm.
]
I can think of two solutions: 1) When all live Realms across all thread are closed, this will also automatically close all frozen Realms or 2) Introduce something like
Realm.closeFrozenRealms(config)
which will do it manually. It is unclear what is better.For now, frozen Realms will all be closed when the live Realm spawning them are. This is primarely driven by making RxJava support easier.
Freeze existing object or return frozen copy?
Should freezing objects return a frozen copy or freeze the object in place?
There are performance benefits to freezing current object, but it seems to conflict with e.g. RxJava support and people need access to the live object in order to get notifications. Kotlin Multiplatform freeze in place.
For now we return frozen copies. I suggest we leave it up to user feedback to see if we should change it. We can consider having an internal method that freezes in-place if it will improve performance a lot.
Equality and hashcode:
How should object equality work for frozen objects? Current RealmLists and RealmLists compare objects on pr. object basis. How should frozen Realms and objects be compared?
For now Frozen objects with the same values are not considered equal to a live object. Same for Realms. Frozen objects at different versions (but equal values) are also not considered equal.
Use cases are unclear. The suggestion is to leave it up to user feedback to see if we should change it.
Generic parameter on
RealmModel
?So it becomes:
RealmModel<MyImplementation>
, e.gpublic class Dog extends RealmObject<Dog>
.This enables better return types on
freeze()
as well as the currentasFlowable()
(which is kinda annoying to use). Setting the parameter is optional in Java (non-breaking), but seems to be required in Kotlin if present.Unclear if we want to break everyone using Kotlin for this, but it will remove a lot of annoying casts. I will defer changing this to a later PR so we can discuss further (and to prevent cluttering this PR too much).
Benchmark results (on Emulator)
Results where frozen with 10.000 objects. It looks like freezing TableViews are fast enough that we don't need to be too concerned about performance. For a more scalable solution we should look into freezing TableViews off the UI thread (but doing it on the notifier thread also seems like a bad idea).
TODO:
RealmObject.freeze()
andRealmObject.isFrozen()
RealmModel.freeze()
andRealmModel.isFrozen()
RealmList.freeze()
andRealmList.isFrozen()
Implement
RealmResults.freeze()
andRealmResults.isFrozen()
Realm.freeze()
andRealm.isFrozen()
DynamicRealm.freeze()
andDynamicRealm.isFrozen()
RxObservableFactory
so it returns frozen objects.RealmConfiguration
to throw at certain number of active versions. Should be checked when we start a write transaction.copyOrUpdate
frozen Realm datainsertOrUpdate
frozen Realm data